/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu 
 * date:2016年4月4日
 *
 */
package com.acooly.module.openapi.client.provider.wewallet.marshall;

import com.google.common.collect.Maps;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.core.utils.validate.Validators;
import com.acooly.module.openapi.client.api.anotation.ApiItem;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.provider.wewallet.WeWalletProperties;
import com.acooly.module.openapi.client.provider.wewallet.domain.WeWalletApiMessage;
import com.acooly.module.openapi.client.provider.wewallet.domain.WeWalletRequest;
import com.acooly.module.openapi.client.provider.wewallet.partner.WeWalletKeyPairManager;
import com.acooly.module.openapi.client.provider.wewallet.utils.JsonMarshallor;
import com.acooly.module.openapi.client.provider.wewallet.utils.SignUtils;
import com.acooly.module.safety.Safes;
import com.acooly.module.safety.signature.SignTypeEnum;
import com.acooly.module.safety.signature.SignerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

/**
 * @author zhangpu
 */
@Slf4j
public class WeWalletMarshallSupport {

    @Autowired
    protected WeWalletProperties weWalletProperties;

    @Autowired
    protected SignerFactory signerFactory;

    @Resource(name = "weWalletGetKeyPairManager")
    private WeWalletKeyPairManager keyPairManager;

    private static JsonMarshallor jsonMarshallor = JsonMarshallor.INSTANCE;

    protected WeWalletProperties getProperties() {
        return weWalletProperties;
    }

    protected String doMarshall(WeWalletRequest source) {
        doVerifyParam(source);
        String reqStr = "";
        if(true){//此处做判断，用哪种加签方式 TODO
            Map<String, String> requestDataMap = getRequestDataMap(source);
            reqStr = SignUtils.getReqContent(requestDataMap,source.getGatewayUrl()+"?");
        }else{
            List<String> values = getRequestDataList(source);
            reqStr = SignUtils.doSign(values,"");
        }
        return reqStr;
    }

    /**
     * 获取代签list
     *
     * @param source
     * @return
     */
    protected List<String> getRequestDataList(WeWalletRequest source) {
        List<String> values=new ArrayList<String>();

        Set<Field> fields = Reflections.getFields(source.getClass());

        Object value = null;
        for (Field field : fields) {
            value = Reflections.getFieldValue(source, field.getName());
            if (value == null) {
                continue;
            }
            ApiItem apiItem = field.getAnnotation(ApiItem.class);
            if (apiItem != null) {
                if (!apiItem.sign()) {
                    continue;
                }
            }
            if (field.getType() != String.class) {
                value = jsonMarshallor.marshall(value);
            }
            if(Strings.isNotBlank((String) value)) {
                values.add((String) value);
            }
        }

        return values;
    }


    /**
     * 获取代签map
     *
     * @param source
     * @return
     */
    protected Map<String, String> getRequestDataMap(WeWalletRequest source) {
        Map<String, String> requestData = Maps.newTreeMap();
        Set<Field> fields = Reflections.getFields(source.getClass());
        String key = null;
        Object value = null;
        for (Field field : fields) {
            value = Reflections.getFieldValue(source, field.getName());
            if (value == null) {
                continue;
            }
            ApiItem apiItem = field.getAnnotation(ApiItem.class);
            if (apiItem == null) {
                key = field.getName();
            } else {
                if (!apiItem.sign()) {
                    continue;
                }
                key = apiItem.value();
                if (Strings.isBlank(key)) {
                    key = field.getName();
                }
            }
            if (field.getType() != String.class) {
                value = jsonMarshallor.marshall(value);
            }
            if(Strings.isNotBlank((String) value)) {
                requestData.put(key, (String) value);
            }
        }
        return requestData;
    }


    /**
     * 验签
     *
     * @param signature
     * @param plain
     * @return
     */
    protected void doVerifySign(String signature, String plain, String partnerId) {
        Safes.getSigner(SignTypeEnum.Rsa.name ()).verify(plain, keyPairManager.getKeyPair(partnerId), signature);
    }


    /**
     * 校验参数
     *
     * @param source
     */
    protected void doVerifyParam(WeWalletApiMessage source) {
        try {
            source.doCheck();
            Validators.assertJSR303(source);
        } catch (Exception e) {
            throw new ApiClientException(e.getMessage());
        }
    }


    protected void beforeMarshall(WeWalletApiMessage message) {
        if(Strings.isBlank(message.getPartnerId())) {
            message.setPartnerId(getProperties().getPartnerId());
        }
    }


    protected String doSign(String waitForSign,String partnerId) {
        return Safes.getSigner(SignTypeEnum.Rsa.name()).sign(waitForSign, keyPairManager.getKeyPair(partnerId));
    }
}
